package es.us.lsi.aws.api.util;

public class Pair<A, B> implements Comparable< Pair <A,B>> {
	private final A mFirst;
	private final B mSecond;

	@SuppressWarnings("unused")
	private Pair(){
		 mFirst = null;
		 mSecond = null;
	}
	
	/**
	 * Preferred constructor
	 * @param pFirst 
	 * @param pSecond
	 */
	public Pair(A pFirst, B pSecond) {
		super();
		this.mFirst = pFirst;
		this.mSecond = pSecond;
	}

	public int hashCode() {
		int hashFirst = mFirst != null ? mFirst.hashCode() : 0;
		int hashSecond = mSecond != null ? mSecond.hashCode() : 0;

		return hashFirst + 31 * hashSecond;
	}

	public boolean equals(Object pOther) {
		if (pOther instanceof Pair<?,?>) {
			@SuppressWarnings("unchecked")
			Pair<?,?> otherPair = (Pair<A,B>) pOther;
			return ((( mFirst == null && otherPair.mFirst == null ) ||
					( mFirst != null && otherPair.mFirst != null &&
					mFirst.equals(otherPair.mFirst))) &&
					(( mSecond == null && otherPair.mSecond == null )||
							( mSecond != null && otherPair.mSecond != null &&
							mSecond.equals(otherPair.mSecond))) );
		}

		return false;
	}

	public String toString()
	{ 
		return "(" + mFirst + ", " + mSecond + ")"; 
	}

	public A getFirst() {
		return mFirst;
	}

	public B getSecond() {
		return mSecond;
	}

	@SuppressWarnings("unchecked")
	public int compareTo(Pair<A, B> pOther) {
		int result = 0;
		try{
			result = ((Comparable<A>) mFirst).compareTo(pOther.getFirst());
			if(result == 0){
				result = ((Comparable<B>) mSecond).compareTo(pOther.getSecond());
			}
		}catch(ClassCastException e){
			result = 0; 
		}
		return result;
	}

}
